package main

import (
	"fmt"
	"strings"
	"sort" // 排序包
)

/*
  切片sort排序
	intList := []int{5, 2, 8, 3, 9, 1}
	float8List := []float64{5.2, 2.3, 8.1, 3.4, 9.5, 1.6}
	stringList := []string{"apple", "banana", "orange", "pear", "grape", "peach"}
	sort.Ints(intList)
	sort.Float64s(float8List)
	sort.Strings(stringList)
	fmt.Println(intList)
	fmt.Println(float8List)
	fmt.Println(stringList)

	降序
	sort.Sort(sort.Reverse(sort.IntSlice(intList)))
	sort.Sort(sort.Reverse(sort.Float64Slice(float8List)))
	sort.Sort(sort.Reverse(sort.StringSlice(stringList)))

*/

func main () {
	// var s1 []int    //定义一个存放int类型元素的切片
	// var s2 []string //定义一个存放string类型元素的切片
	// fmt.Println(s1, s2)
	// // 一个切片在未初始化之前默认为 nil，长度为 0
	// fmt.Println(s1 == nil) //true  为空  没有开辟内存空间
	// fmt.Println(s2 == nil) //true

	var s1 = []int{1, 2, 3}
	var s2 = []string{"北苑", "长阳", "望京"}
	fmt.Println(s1, s2)
	fmt.Println(s1 == nil) //false
	fmt.Println(s2 == nil) //false

	// 分别使用len()、cap()获得切片的长度和容量  一个汉字占用3个字节  一个英文字母占用1个字节
	fmt.Printf("len(s1):%d cap(s1):%d\n", len(s1), cap(s1))
	fmt.Printf("len(s2):%d cap(s2):%d\n", len(s2), cap(s2))

	// 定义一个数组
	a1 := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	s3 := a1[0:4] // 基于一个数组切割 [0:4]左包含 右不包含
	fmt.Println(s3)  // [1 2 3 4]
	s5 := a1[:4] //[1 2 3 4]
	s6 := a1[2:] //[3 4 5 6 7 8 9] 成一个新的切片
	s7 := a1[:]  //[1 2 3 4 5 6 7 8 9] 获取所有的元素 成一个新的切片
	fmt.Println(s5)
	fmt.Println(s6)
	fmt.Println(s7)
	fmt.Printf("len(s5):%d cap(s5):%d\n", len(s5), cap(s5)) //4 9
	// 从这里看出len是数组中元素的个数，cap是数组的容量
	// 容量切左不切右，长度切左右都包含
	fmt.Printf("len(s6):%d cap(s6):%d\n", len(s6), cap(s6)) //7 7
	fmt.Printf("len(s7):%d cap(s7):%d\n", len(s7), cap(s7)) //9 9

	s8 :=s6[3:]
	//s8的值为：6 7 8 9
	fmt.Printf("len(s8):%d cap(s8):%d\n", len(s8), cap(s8)) //4 4

	fmt.Println("~~~~~~~~~~~~~~~~~~~")

	numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	numbers = append(numbers, 0) // 不能通过下标方式给切片扩容，只能通过append()函数
	fmt.Println(numbers) //[1 2 3 4 5 6 7 8 9 0]
	numbers = append(numbers, 10, 11, 12)
	fmt.Println(numbers) //[1 2 3 4 5 6 7 8 9 0 10 11 12]
	numbers1 := make([]int, len(numbers), (cap(numbers)) * 2) // 扩容2倍
	copy(numbers1, numbers) // 使用copy()函数将numbers复制到numbers1
	// numbers1, numbers 两个变化互不影响
	fmt.Println(numbers1) //[1 2 3 4 5 6 7 8 9 0 10 11 12]
	fmt.Printf("len(numbers1):%d cap(numbers1):%d\n", len(numbers1), cap(numbers1)) //13 26

	// make() 函数创建切片
	var sliceA = make([]int , 4, 8) // 切片A的容量为8，长度为4
	fmt.Println(sliceA) //[0 0 0 0]
	sliceB := make([]int, 2, 4) // 切片B的容量为4，长度为2
	fmt.Println(sliceB) //[0 0]
	sliceC := append(sliceA, sliceB...) // 合并切片A和切片B
	fmt.Println(sliceC) //[0 0 0 0 0 0]
	fmt.Printf("len(sliceC):%d cap(sliceC):%d\n", len(sliceC), cap(sliceC)) //6 8

	// go中没有切片删除元素的方法
	// 但是可以通过切片的切割来删除元素
	sliceD := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	// 删除索引为2的元素
	sliceD = append(sliceD[:2], sliceD[3:]...)
	fmt.Println(sliceD) //[1 2 4 5 6 7 8 9]

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	var str1 = "123-456-789" // 将字符串转化为切片
	arr := strings.Split(str1, "-")
	fmt.Println(arr) //[123 456 789]

	str2 := strings.Join(arr, ",")
	fmt.Println(str2) //123,456,789

	// strings.contains() 判断字符串是否包含子串
	fmt.Println(strings.Contains(str1, "123")) //true
	fmt.Println(strings.Contains(str1, "abc")) //false

	// strings.count() 统计字符串中子串出现的次数
	fmt.Println(strings.Count(str1, "123")) //1
	fmt.Println(strings.Count(str1, "abc")) //0

	// strings.replace() 替换字符串中的子串
	fmt.Println(strings.Replace(str1, "123", "abc", -1)) //abc-456-789

	// strings.index() 寻找子串的位置
	fmt.Println(strings.Index(str1, "123")) //0
	fmt.Println(strings.Index(str1, "abc")) //-1 查找不到

	// strings.lastIndex() 寻找子串最后一次出现的位置
	fmt.Println(strings.LastIndex(str1, "123")) //0
	fmt.Println(strings.LastIndex(str1, "abc")) //-1 查找不到

	// 前后缀判断
	fmt.Println(strings.HasPrefix(str1, "123")) //true
	fmt.Println(strings.HasPrefix(str1, "abc")) //false
	fmt.Println(strings.HasSuffix(str1, "789")) //true
}